
//Copyright 1997-2009 Syrinx Development, Inc.
//This file is part of the Syrinx Web Application Framework (SWAF).
// == BEGIN LICENSE ==
//
// Licensed under the terms of any of the following licenses at your
// choice:
//
//  - GNU General Public License Version 3 or later (the "GPL")
//    http://www.gnu.org/licenses/gpl.html
//
//  - GNU Lesser General Public License Version 3 or later (the "LGPL")
//    http://www.gnu.org/licenses/lgpl.html
//
//  - Mozilla Public License Version 1.1 or later (the "MPL")
//    http://www.mozilla.org/MPL/MPL-1.1.html
//
// == END LICENSE ==
using System;
using System.Diagnostics;
using System.IO;

using Swaf;
using Swaf.BizRule;
using Swaf.BizObj;
using Swaf.Container;

using Syrinx;

namespace MediaCache
{
	/// <summary>Provides basic, read only access bizrules for the mediacache feature of the framework gallery.
	/// The non-read only bizrules are contained within the MediaCacheAdmin.BusinessRules class.
    /// All of the bizrules in this class will throw a MediaCacheException if a failure occur.
	/// </summary>
	public class BusinessRules : Syrinx.BaseBizRules
	{
        /// <summary>
        /// Returns a bizobj list of MediaItem bizobjs that are located within the given directory specified as
        /// a parameter.  The MediaItem bizobjs do not contain the actual image data, just the basic information
        /// about it.</summary>
        /// <param name="fromRootName">The root directory to return the image bizobj list from.</param>
        /// <param name="deep">If true, this method will return all the images within all the sub directories
        /// contained within the given this root.</param>
		public IBizObjList getImageList(IApplication app, IRuleContext context, string fromRootName, bool deep)
		{
            if (fromRootName == null)
                throw new MediaCacheException("the rootname cannot be null");

			BaseImageCache ic = (MediaCache.BaseImageCache)app.appData.get("images." + fromRootName);
			ImageListType t = (deep)?ImageListType.deepFiles:ImageListType.filesOnly;
			IBizObjList imageObjs = ic.getImages(t, null);
			return imageObjs;
		}

        /// <summary>Provides a MediaStream for the given image if found.  
        /// </summary>
        /// <param name="name">The name of the image to return the MediaStream for.  Should include
        /// the fully qualified catalog name and directory name the image is located in. Example:
        /// images.cacheCatalogName.ImgAjdustName.path.imageName</param> 
        /// <returns>The MediaStream of the image data or null if the given name is not found in the media cache.</returns>
		public MediaStream getImage(IApplication app, IRuleContext context, string name)
		{
			MediaStream media = (MediaStream)app.appData.get(name, "asMediaStream");
			return media;
		}

        /// <summary>Provides a MediaLocation bizobjlist based on the given starting directory.  This does not provide
        /// the actual MediaItems in the given directories, just the MediaLocation bizobjs.  Note that the MediaLocation
        /// biizobjlist is actual a tree structure of MediaLocation bizobjs that is based on the actual directory structure
        /// within the media cache.
        /// </summary>
        /// <param name="cacheName">The cache catalog name the directories are to come from.</param>
        /// <param name="dummy">a dummy variable to avoid the rulemanager bug involving the 2nd param being a string</param>
        /// <param name="pathName">the root directory to start the bizobj list from</param>
        /// <returns>The MediaLocation bizobjlist of directories from the given media cache.</returns>
        public IBizObjList getMediaLocationDirectories(IApplication app, IRuleContext context, string cacheName,bool dummy, string pathName)
        {
            try
            {
                pathName = (pathName == null ? "" : pathName);
                MediaCache.BaseImageCache ic = (MediaCache.BaseImageCache)app.appData.get("images." + cacheName);
                IBizObjList mediaList = app.bizObjMgr.createList("MediaLocation");
                IBizObj root = mediaList.insertNew();
                root.put("name", "");
                root.put("fullName", "");
                root.put("childDirs", ic.getLocations(pathName));
                return mediaList;
            }
            catch (Exception e)
            {
                throw new MediaCacheException("Error executing getMediaLocation bizRule", e);
            }
        }

        /// <summary>Provides a MediaItem bizobj list from the specified media cache and the location within it.  The
        /// MediaITem bizobjs do not contain the actual media, only the name and other details about it.
        /// </summary>
        /// <param name="cacheName">The cache catalog name the MediaItems will come from</param>
        /// <param name="listOf">Indicates if the list should include MediaItems from child directories contained within
        /// the starting directory.</param>
        /// <param name="path">The path the MediaItems are to come from.</param>
        /// <returns>The MediaItem bizobjlist.</returns>
        public IBizObjList getMediaItemsFromDirectory(IApplication app, IRuleContext context, 
            string cacheName, MediaCache.ImageListType listOf, string path)
        {
            if (cacheName == null)
                throw new MediaCacheException("the cacheName cannot be null");

            try
            {
                MediaCache.BaseImageCache ic = (MediaCache.BaseImageCache)app.appData.get("images." + cacheName);
                IBizObjList list= ic.getImages(path, listOf, null);
				return list;
            }
            catch (Exception e)
            {
                throw new MediaCacheException("Error executing getMediaItemsFromDirectory bizRule", e);
            }


        }

        /// <summary>
        /// Given an Image bizobj, will look at the file details of the image from the cache and return the EXF
        /// properties contained within the file.  This includes things like when the picture was take.
        /// </summary>
        /// <param name="image">The image bizobj with the media cache name, directory name and image name
        /// to retrieve the data with.</param>
        /// <returns>The same image object passed in with its imageProperites field populated with whatever
        /// EXF properties existed in the image file.</returns>
        public IBizObj getImageFileInfo(IApplication app, IRuleContext context, IBizObj image)
        {
            if (image == null)
                throw new MediaCacheException("the image cannot be null");

            try
            {
                string cachePath = image.get("location").ToString();
                MediaCache.BaseImageCache ic = (MediaCache.BaseImageCache)app.appData.get("images." + cachePath);
                image.put("imageProperties", ic.getImageFileInfo(image.get("name").ToString()));
                return image;
            }
            catch (Exception e)
            {
                throw new MediaCacheException("Error executing getPictureFileInfo bizRule", e);
            }
        }

        /// <summary>
        /// Given a media cache name, will return a MediaCache bizobj of all its details include its
        /// scalings and image adjustments.  This is the contents of the media cache's catalog entry.
        /// </summary>
        /// <param name="id">The media cache name to get the details for</param>
        /// <returns>The populated MediaCache bizobj or null if the given media cache does not exist.</returns>
        public IBizObj getImageCacheDetails(IApplication app,IRuleContext context, string id)
        {
            if (id == null)
                throw new MediaCacheException("the passed id cannot be null");

            try
            {
                IBizObj imgCacheInfo = null;
                FlexiMap m = new FlexiMap();
                m["id"] = id;
                IBizObjList caches = app.appData.get("Data.MediaCache.GetMediaCacheLibrary",m) as IBizObjList;
                if (caches != null && caches.numElements > 0)
                {
                    BaseImageCache imageCache = app.appData.get("images." + id) as BaseImageCache;
                    imgCacheInfo = imageCache.CacheConfig.Clone() as IBizObj;
                    imgCacheInfo.put("id", id);
                    imgCacheInfo.put("isDefault", caches[0].get("isDefault"));
					imgCacheInfo.isNew = false;
                }
                return imgCacheInfo;
            }
            catch (Exception e)
            {
                throw new MediaCacheException("Error executing getImageCacheDetails bizrule.", e);
            }
        }
		
		
		public IBizObjList getMediaItemDirectories(IApplication app, IRuleContext context, string cacheName)
		{
			try
			{
				IBizObjList list = app.bizObjMgr.createList("MediaItemDirectory");
				IBizObj root = list.insertNew();
				MediaCache.BaseImageCache ic = (MediaCache.BaseImageCache)app.appData.get("images." + cacheName);
				string path = app.resMgr.resolve(ic.CacheConfig.get("origionalImagesLocation").ToString());

				root.put("parentName", null);
				root.put("name", "Root");
				root.put("keyName", "");
				root.put("depth", 0);
				root.put("cacheName", cacheName);
				root.put("fileCount", fileCount(new DirectoryInfo(path)));
				root.clearDirtyFlags();
				root.isNew = false;

				calcMediaItemDirectory(path, list, path.Length, cacheName);
				
				return list;
			}
			catch (Exception e)
			{
				throw new MediaCacheException("error executing getMediaItemDirectories.", e);
			}
		}

		protected IBizObjList calcMediaItemDirectory(string path, IBizObjList list, int pos,string cacheName)
		{
			DirectoryInfo di = new DirectoryInfo(path);
			
			foreach (DirectoryInfo childDir in di.GetDirectories())
			{
				IBizObj directory = list.insertNew();
				Swaf.BGuid.Guid pid = new Swaf.BGuid.Guid();
				string keyName = childDir.FullName.Substring(pos).Replace(Path.DirectorySeparatorChar, ':');
				int index = keyName.LastIndexOf(':');
				if(index != -1)
					directory.put("parentName", keyName.Substring(0, index));
				else
					directory.put("parentName", null);
				directory.put("name", childDir.Name);
				directory.put("keyName", keyName);
				directory.put("depth", calcDirectoryPosition(keyName));
				directory.put("cacheName", cacheName);
				directory.put("fileCount", fileCount(childDir));
				directory.clearDirtyFlags();
				directory.isNew = false;
				calcMediaItemDirectory(childDir.FullName, list, pos,cacheName);
			}
			return list;
		}

		protected int fileCount(DirectoryInfo dir)
		{
			int count=0;
			string[] filters = "*.jpg;*.jpeg;*.tif;*.tiff;*.gif;*.bmp;*.png".Split(';');
			for (int i = 0; i < filters.Length; i++)
				count += dir.GetFiles(filters[i]).Length;
			return count;
		}
		protected int calcDirectoryPosition(string str)
		{
			int i = 1;
			for (int x = 0; x < str.Length; x++)
				if (str[x].Equals(':'))
					i++;
			return i;
		}

    }
}
